<!-- eslint-disable no-useless-escape -->
<script setup lang="ts">
import type { InfraCodegenApi } from '#/api/infra/codegen';

import { onMounted, ref, unref, watch } from 'vue';

import { isString } from '@vben/utils';

import formCreate from '@form-create/ant-design-vue';
import FcDesigner from '@form-create/antd-designer';
import { useClipboard } from '@vueuse/core';
import { Button, message, Modal } from 'ant-design-vue';
import hljs from 'highlight.js';
import xml from 'highlight.js/lib/languages/java';
import json from 'highlight.js/lib/languages/json';

import { useFormCreateDesigner } from '#/components/form-create';

import 'highlight.js/styles/github.css';

defineOptions({ name: 'FormBuilder' });

interface Props {
  table: InfraCodegenApi.CodegenTable;
  columns: InfraCodegenApi.CodegenColumn[];
}

const props = defineProps<Props>();
const emit = defineEmits(['form-change']);

const designer = ref(); // 表单设计器

// 表单设计器配置
const designerConfig = ref({
  switchType: [], // 是否可以切换组件类型,或者可以相互切换的字段
  autoActive: true, // 是否自动选中拖入的组件
  useTemplate: false, // 是否生成vue2语法的模板组件
  formOptions: {
    form: {
      labelWidth: '100px', // 设置默认的 label 宽度为 100px
    },
  }, // 定义表单配置默认值
  fieldReadonly: false, // 配置field是否可以编辑
  hiddenDragMenu: false, // 隐藏拖拽操作按钮
  hiddenDragBtn: false, // 隐藏拖拽按钮
  hiddenMenu: [], // 隐藏部分菜单
  hiddenItem: [], // 隐藏部分组件
  hiddenItemConfig: {}, // 隐藏组件的部分配置项
  disabledItemConfig: {}, // 禁用组件的部分配置项
  showSaveBtn: false, // 是否显示保存按钮
  showConfig: true, // 是否显示右侧的配置界面
  showBaseForm: true, // 是否显示组件的基础配置表单
  showControl: true, // 是否显示组件联动
  showPropsForm: true, // 是否显示组件的属性配置表单
  showEventForm: true, // 是否显示组件的事件配置表单
  showValidateForm: true, // 是否显示组件的验证配置表单
  showFormConfig: true, // 是否显示表单配置
  showInputData: true, // 是否显示录入按钮
  showDevice: true, // 是否显示多端适配选项
  appendConfigData: [], // 定义渲染规则所需的formData
});

const dialogVisible = ref(false); // 弹窗的是否展示
const dialogTitle = ref(''); // 弹窗的标题
const formType = ref(-1); // 表单的类型：0 - 生成 JSON；1 - 生成 Options；2 - 生成组件
const formData = ref(''); // 表单数据
const formRule = ref([]); // 表单规则，用于保存和提交

useFormCreateDesigner(designer); // 表单设计器增强

/** 初始化表单构建器 */
function initFormBuilder() {
  if (designer.value && props.columns) {
    // 根据字段信息生成默认的表单规则
    const rules = generateFormRules(props.columns);
    if (rules.length > 0) {
      designer.value.setRule(rules);
    }
  }
}

/** 根据数据库字段生成表单规则 */
function generateFormRules(columns: InfraCodegenApi.CodegenColumn[]) {
  const rules: any[] = [];
  
  // 过滤出允许创建或更新的字段
  const editableColumns = columns.filter(col => 
    (col.createOperation === 1 || col.updateOperation === 1) && 
    !isSystemField(col.javaField)
  );
  
  editableColumns.forEach((col, index) => {
    const rule: any = {
      type: getFormComponentType(col),
      field: col.javaField,
      title: col.columnComment || col.javaField,
      info: '',
      props: {
        placeholder: `请输入${col.columnComment || col.javaField}`,
      },
      validate: [],
    };
    
    // 必填验证
    if (!col.nullable) {
      rule.validate.push({
        message: `${col.columnComment || col.javaField}不能为空`,
        required: true,
        type: 'string',
        trigger: 'blur',
      });
    }
    
    // 根据字段类型设置特殊属性
    switch (col.javaType) {
      case 'Integer':
      case 'Long':
      case 'Double':
      case 'Float':
      case 'BigDecimal':
        rule.type = 'InputNumber';
        rule.props.style = { width: '100%' };
        break;
      case 'Boolean':
        rule.type = 'Switch';
        rule.props = {
          checkedChildren: '是',
          unCheckedChildren: '否',
        };
        break;
      case 'Date':
      case 'LocalDate':
        rule.type = 'DatePicker';
        rule.props = {
          placeholder: `请选择${col.columnComment || col.javaField}`,
          format: 'YYYY-MM-DD',
          valueFormat: 'YYYY-MM-DD',
        };
        break;
      case 'LocalDateTime':
        rule.type = 'DateTimePicker';
        rule.props = {
          placeholder: `请选择${col.columnComment || col.javaField}`,
          format: 'YYYY-MM-DD HH:mm:ss',
          valueFormat: 'YYYY-MM-DD HH:mm:ss',
          showTime: true,
        };
        break;
    }
    
    // 字典类型处理
    if (col.dictType) {
      rule.type = 'Select';
      rule.props = {
        placeholder: `请选择${col.columnComment || col.javaField}`,
        options: [], // 这里可以根据dictType获取选项
      };
    }
    
    // 文本域处理
    if (col.htmlType === 'textarea') {
      rule.type = 'Textarea';
      rule.props = {
        ...rule.props,
        rows: 4,
        maxlength: 500,
        showCount: true,
      };
    }
    
    rules.push(rule);
  });
  
  return rules;
}

/** 获取表单组件类型 */
function getFormComponentType(column: InfraCodegenApi.CodegenColumn): string {
  if (column.dictType) return 'Select';
  
  switch (column.javaType) {
    case 'Boolean': return 'Switch';
    case 'Date':
    case 'LocalDate': return 'DatePicker';
    case 'LocalDateTime': return 'DateTimePicker';
    case 'Integer':
    case 'Long':
    case 'Double':
    case 'Float':
    case 'BigDecimal': return 'InputNumber';
    default: return 'Input';
  }
}

/** 判断是否为系统字段 */
function isSystemField(fieldName: string): boolean {
  const systemFields = [
    'id', 'createTime', 'updateTime', 'createBy', 'updateBy',
    'creator', 'updater', 'createUser', 'updateUser', 'deleted'
  ];
  return systemFields.includes(fieldName);
}

/** 监听表单变化 */
function onFormChange() {
  if (designer.value) {
    const rule = designer.value.getRule();
    const option = designer.value.getOption();
    formRule.value = rule;
    
    // 通知父组件表单配置发生变化
    emit('form-change', {
      rule,
      option,
      json: formCreate.toJson(rule),
    });
  }
}

/** 打开弹窗 */
function openModel(title: string) {
  dialogVisible.value = true;
  dialogTitle.value = title;
}

/** 生成 JSON */
function showJson() {
  openModel('生成 JSON');
  formType.value = 0;
  formData.value = designer.value.getRule();
}

/** 生成 Options */
function showOption() {
  openModel('生成 Options');
  formType.value = 1;
  formData.value = designer.value.getOption();
}

/** 生成组件 */
function showTemplate() {
  openModel('生成组件');
  formType.value = 2;
  formData.value = makeTemplate();
}

/** 生成组件代码 */
function makeTemplate() {
  const rule = designer.value.getRule();
  const opt = designer.value.getOption();
  return `<template>
  <form-create
    v-model:api="fApi"
    :rule="rule"
    :option="option"
    @submit="onSubmit"
  ></form-create>
</template>
<script setup lang=ts>
  const faps = ref(null)
  const rule = ref('')
  const option = ref('')
  const init = () => {
    rule.value = formCreate.parseJson('${formCreate.toJson(rule).replaceAll('\\', '\\\\')}')
    option.value = formCreate.parseJson('${JSON.stringify(opt, null, 2)}')
  }
  const onSubmit = (formData) => {
    //todo 提交表单
  }
  init()
<\/script>`;
}

/** 复制 */
async function copy(text: string) {
  const textToCopy = JSON.stringify(text, null, 2);
  const { copy, copied, isSupported } = useClipboard({ source: textToCopy });
  if (isSupported) {
    await copy();
    if (unref(copied)) {
      message.success('复制成功');
    }
  } else {
    message.error('复制失败');
  }
}

/** 代码高亮 */
function highlightedCode(code: string) {
  // 处理语言和代码
  let language = 'json';
  if (formType.value === 2) {
    language = 'xml';
  }
  
  if (!isString(code)) {
    code = JSON.stringify(code, null, 2);
  }
  
  // 高亮
  const result = hljs.highlight(code, { language, ignoreIllegals: true });
  return result.value || '&nbsp;';
}

/** 获取表单配置（供父组件调用） */
function getFormConfig() {
  if (designer.value) {
    const rule = designer.value.getRule();
    const option = designer.value.getOption();
    return {
      rule,
      option,
      json: formCreate.toJson(rule),
    };
  }
  return null;
}

/** 设置表单配置（供父组件调用） */
function setFormConfig(config: any) {
  if (designer.value && config) {
    if (config.rule) {
      designer.value.setRule(config.rule);
    }
  }
}

// 暴露方法给父组件
defineExpose({
  getFormConfig,
  setFormConfig,
  onFormChange,
});

// 监听props变化，重新初始化
watch([() => props.table, () => props.columns], () => {
  initFormBuilder();
}, { deep: true });

/** 初始化 */
onMounted(async () => {
  // 注册代码高亮的各种语言
  hljs.registerLanguage('xml', xml);
  hljs.registerLanguage('json', json);
  
  // 初始化表单构建器
  setTimeout(() => {
    initFormBuilder();
  }, 500);
});
</script>

<template>
  <div class="form-builder-container">
    <div class="mb-4">
      <h3 class="text-lg font-medium text-gray-900">表单构建器</h3>
      <p class="mt-1 text-sm text-gray-500">
        通过拖拽的方式设计表单，系统已根据字段信息预生成基础表单结构，你可以进一步调整和优化。
      </p>
    </div>
    
    <FcDesigner 
      ref="designer" 
      height="70vh" 
      :config="designerConfig"
      @change="onFormChange"
    >
      <template #handle>
        <Button size="small" type="primary" ghost @click="showJson">
          生成JSON
        </Button>
        <Button size="small" type="primary" ghost @click="showOption">
          生成Options
        </Button>
        <Button size="small" type="primary" ghost @click="showTemplate">
          生成组件
        </Button>
      </template>
    </FcDesigner>

    <!-- 弹窗：代码预览 -->
    <Modal 
      v-model:open="dialogVisible"
      :title="dialogTitle" 
      :footer="false" 
      width="800px"
      :destroy-on-close="true"
    >
      <div>
        <Button style="float: right" @click="copy(formData)"> 
          复制 
        </Button>
        <div class="mt-4">
          <pre><code v-dompurify-html="highlightedCode(formData)" class="hljs"></code></pre>
        </div>
      </div>
    </Modal>
  </div>
</template>

<style scoped>
.form-builder-container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.hljs {
  padding: 16px;
  border-radius: 6px;
  background-color: #f6f8fa;
  font-size: 14px;
  line-height: 1.45;
  overflow-x: auto;
}
</style>